package main

import (
	"context"
	"fmt"
	"github.com/hashicorp/consul/api"
	consulapi "github.com/hashicorp/consul/api"
	"google.golang.org/grpc"
	"google.golang.org/grpc/health"
	"google.golang.org/grpc/health/grpc_health_v1"
	"google.golang.org/protobuf/types/known/emptypb"
	"load_balance/proto"
	"log"
	"net"
)

//https://www.cnblogs.com/liuqingzheng/p/16296785.html
type Service struct {
}

func (s Service) Test(ctx context.Context, empty *emptypb.Empty) (*proto.TestResponse, error) {
	fmt.Println("收到一个请求")
	return &proto.TestResponse{Msg: "test ha ha ha ha ha"}, nil
}

const (
	consulAddress = "100.100.142.83:8500"
)

func main() {
	// 服务注册
	// 1.初始化 consul 配置
	consulConfig := api.DefaultConfig()
	consulConfig.Address = consulAddress

	// 2.创建 consul 对象
	consulClient, err := api.NewClient(consulConfig)
	if err != nil {
		fmt.Println("consul client error : ", err)
	}

	// 3.注册的服务配置
	reg := api.AgentServiceRegistration{
		//ID:   fmt.Sprintf("%s", strings.ReplaceAll(uuid.NewV4().String(), "-", "")),
		ID:      "userService",
		Name:    "userService",
		Tags:    []string{"consul", "grpc"},
		Port:    8081,
		Address: "127.0.0.1",
		Check: &api.AgentServiceCheck{
			CheckID:                        "consul grpc test",
			Timeout:                        "5s",  // 超时时间
			DeregisterCriticalServiceAfter: "30s", // 触发注销的时间
			TTL:                            "15s",
			//Interval:                       "15s",
			//TCP:  "127.0.0.1:8081",
			//GRPC: fmt.Sprintf("%s:%d", "127.0.0.1", 8081),
		},
	}

	// 4. 注册 grpc 服务到 consul 上
	err = consulClient.Agent().ServiceRegister(&reg)
	if err != nil {
		log.Fatalf("注册服务失败: %s", err.Error())
	}

	//////////////////////以下为 grpc 服务远程调用////////////////////////
	listener, err := net.Listen("tcp", "127.0.0.1:8081")
	if err != nil {
		log.Fatalf("监听端口:%d失败: %s", 8081, err.Error())
	}
	defer listener.Close()

	fmt.Println("server start...")

	grpcServer := grpc.NewServer()
	proto.RegisterTestServer(grpcServer, &Service{})
	// grpc注册服务的健康检查
	grpc_health_v1.RegisterHealthServer(grpcServer, health.NewServer())
	err = grpcServer.Serve(listener)
	if err != nil {
		log.Fatalf("grpcServer服务失败: %s", err.Error())
	}
}

func RegisterConsul(localIP string, localPort int, name string, id string, tags []string) error {
	// 创建连接consul服务配置
	config := consulapi.DefaultConfig()
	config.Address = consulAddress
	client, err := consulapi.NewClient(config)
	if err != nil {
		fmt.Println("consul client error : ", err)
	}

	// 创建注册到consul的服务到
	registration := new(consulapi.AgentServiceRegistration)
	registration.ID = id
	registration.Name = name //根据这个名称来找这个服务
	registration.Port = localPort
	//registration.Tags = []string{"lqz", "web"} //这个就是一个标签，可以根据这个来找这个服务，相当于V1.1这种
	registration.Tags = tags //这个就是一个标签，可以根据这个来找这个服务，相当于V1.1这种
	registration.Address = localIP

	// 增加consul健康检查回调函数
	check := new(consulapi.AgentServiceCheck)
	check.HTTP = fmt.Sprintf("http://%s:%d/health", registration.Address, registration.Port)
	check.Timeout = "5s"                         //超时
	check.Interval = "5s"                        //健康检查频率
	check.DeregisterCriticalServiceAfter = "30s" // 故障检查失败30s后 consul自动将注册服务删除
	registration.Check = check
	// 注册服务到consul
	err = client.Agent().ServiceRegister(registration)
	if err != nil {
		return err
	}
	return nil
}

// 取消consul注册的服务
func DeleteService() error {
	// 创建连接consul服务配置
	config := consulapi.DefaultConfig()
	config.Address = consulAddress
	client, err := consulapi.NewClient(config)
	if err != nil {
		fmt.Println("consul client error : ", err)
	}
	err = client.Agent().ServiceDeregister("qqq")
	if err != nil {
		return err
	}
	return nil
}

// 注册服务到consul
func ConsulRegister() {
	// 创建连接consul服务配置
	config := consulapi.DefaultConfig()
	config.Address = "172.16.242.129:8500"
	client, err := consulapi.NewClient(config)
	if err != nil {
		log.Fatal("consul client error : ", err)
	}

	// 创建注册到consul的服务到
	registration := new(consulapi.AgentServiceRegistration)
	registration.ID = "111"
	registration.Name = "go-consul-test"
	registration.Port = 8081
	registration.Tags = []string{"go-consul-test"}
	registration.Address = "10.13.153.128"

	// 增加consul健康检查回调函数
	check := new(consulapi.AgentServiceCheck)
	check.HTTP = fmt.Sprintf("http://%s:%d", registration.Address, registration.Port)
	check.Timeout = "5s"
	check.Interval = "5s"
	check.DeregisterCriticalServiceAfter = "30s" // 故障检查失败30s后 consul自动将注册服务删除
	registration.Check = check

	// 注册服务到consul
	err = client.Agent().ServiceRegister(registration)
}

// 从consul中发现服务
func ConsulFindServer() {
	// 创建连接consul服务配置
	config := consulapi.DefaultConfig()
	config.Address = "172.16.242.129:8500"
	client, err := consulapi.NewClient(config)
	if err != nil {
		log.Fatal("consul client error : ", err)
	}

	// 获取所有service
	services, _ := client.Agent().Services()
	for _, value := range services {
		fmt.Println(value.Address)
		fmt.Println(value.Port)
	}

	fmt.Println("=================================")
	// 获取指定service
	service, _, err := client.Agent().Service("111", nil)
	if err == nil {
		fmt.Println(service.Address)
		fmt.Println(service.Port)
	}
}

func ConsulCheckHeath() {
	// 创建连接consul服务配置
	config := consulapi.DefaultConfig()
	config.Address = "172.16.242.129:8500"
	client, err := consulapi.NewClient(config)
	if err != nil {
		log.Fatal("consul client error : ", err)
	}
	// 健康检查
	a, b, _ := client.Agent().AgentHealthServiceByID("111")
	fmt.Println(a)
	fmt.Println(b)
}

func ConsulKVTest() {
	// 创建连接consul服务配置
	config := consulapi.DefaultConfig()
	config.Address = "172.16.242.129:8500"
	client, err := consulapi.NewClient(config)
	if err != nil {
		log.Fatal("consul client error : ", err)
	}

	// KV, put值
	values := "test"
	key := "go-consul-test/172.16.242.129:8100"
	_, err = client.KV().Put(&consulapi.KVPair{Key: key, Flags: 0, Value: []byte(values)}, nil)

	// KV get值
	data, _, _ := client.KV().Get(key, nil)
	fmt.Println(string(data.Value))

	// KV list
	datas, _, _ := client.KV().List("go", nil)
	for _, value := range datas {
		fmt.Println(value)
	}

	keys, _, _ := client.KV().Keys("go", "", nil)
	fmt.Println(keys)
}
